﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows;
using System.Collections.ObjectModel;
using OperGui.ViewModel;
using System.Windows.Controls;
using OperGui.Models;
using System.Xml;
using VI.Fsc.OperatorGui.Models.Application;
using VI.Fsc.OperatorGui.Models.Application.Util;
using VI.Fsc.OperatorGui.Models.Fsc;
using VI.Fsc.OperatorGui.Models.Fsc.Configuration;
using VI.Fsc.OperatorGui.Models.Subscription;
using System.IO;
using System.Windows.Resources;
using System.Xml.Linq;
using System.Threading;
using VI.Fsc.OperatorGui.WebReferences.Opc;
using VI.Fsc.Common.Util;


namespace OperGui
{
    public class MainWindowViewModel : ViewModelBase
    {
        #region field
        FrameworkElement _currentView;
        string _performance;
        public string NVB;
        string IP;
        // DispatcherTimer Ctimer;
        public string Ctime;
        public int listN;
        ObservableCollection<CommandViewModel> _commands;
        private Views.IPwindow ipconfigView;
        CFsc fsc;
        private delegate void HandleSystemStateChangedCallback(SubscribePolledRefreshReplyItemList[] listOfChanges);
        private SystemState systemState;
        string systemStateSubscriptionId;
        public int _InitialPGB;
        public string _ProgressBarEventName="Initializing Connection Status...";
        #endregion

        #region constructor
        public MainWindowViewModel()
        {
            ////initialize timer
            //Ctimer = new DispatcherTimer();
            //Ctimer.Interval = TimeSpan.FromSeconds(1.0);
            //Ctimer.Start();
            //Ctimer.Tick += new EventHandler(delegate(object s, EventArgs a)
            //{
            //    Currenttime = "" + DateTime.Now.Hour + ":" +
            //    DateTime.Now.Minute + ":" + DateTime.Now.Second + "   " + DateTime.Now.Day + "/" + DateTime.Now.Month + "/" + DateTime.Now.Year;
            //});

            fsc = new CFsc();

            //Load Initial page
            CurrentView = new Views.ProgressBar();
            Commands.Add(new CommandViewModel("Initial Page", null, new RelayCommand(e => this.ViewSwitch("Initial Page"))));
            initializeConnection();
        }



        void initializeConnection()
        {
            // Events listeners for the connection status.
            COPCServerConnectionService.Instance.ConnectionStatusChanged +=
                new ConnectionStatusChangedHandler(HandleConnectionStatusChanged);
            CFscConfigurationFileReader fr = new CFscConfigurationFileReader();
            XmlDocument section = new XmlDocument();
            section.Load("Controllers/Configuration/Vision.exe.config");
            XmlElement node = section.DocumentElement;
            fr.Create(null, null, node["fscconfig"]);
            //Events of the FSC configuration reader.
            //CFscStructureReader.Instance.ReadRemoteFscStructureUpdateEvent +=
            //    new ReadRemoteFscConfigurationUpdateEventHandler(IncreaseProgressDialogValue);
            CFscStructureReader.Instance.ReadRemoteFscStructureFinishEvent +=
                new ReadRemoteFscConfigurationFinishEventHandler(HandleReadRemoteFscConfigurationFinish);
            fsc.FscStartupProgressUpdateEvent += new FscStartupProgressUpdateEventHandler(IncreaseProgressDialogValue);
             //Events if the FSC object.
            fsc.FscErrorEvent += new FscErrorEventHandler(CFscErrorHandler.Instance.HandleError);
            fsc.NewErrorsEvent +=
                new NewErrorsEventHandler(DataDispacher.Instance.HandleNewComponentsErrors);
            fsc.SetSpeedEvent += new SetSpeedEventHandler(HandleSetSpeed);
            fsc.NewModeEvent += new NewModeEventHandler(HandleNewModeEvent);
            //fsc.FscStartupFailedEvent += new FscStartupFailedEventHandler(HandleFscStartupFailed);
            //fsc.FscVersionInfoEvent += new FscVersionInfoEventHandler(HandleVersionInfoEvent);
            COPCServerConnectionService.Instance.Init();
            CSoapServerConnectionService.Instance.Init();


        }
        #endregion
        void ChangeFscSpeed(bool increase)
        {
            int nextSpeedIndex = -1;
            int currentSpeed = this.fsc.Speed;

            if (increase)
            {
                // Finds the next higher speed.
                for (int i = 0; i < CFscConfiguration.Instance.PossibleSpeedValues.Count; i++)
                {
                    if (currentSpeed < CFscConfiguration.Instance.PossibleSpeedValues[i])
                    {
                        nextSpeedIndex = i;
                        break;
                    }
                }
            }
            else
            {
                // Finds the next lower speed.
                for (int i = CFscConfiguration.Instance.PossibleSpeedValues.Count - 1; i >= 0; i--)
                {
                    if (currentSpeed > CFscConfiguration.Instance.PossibleSpeedValues[i])
                    {
                        nextSpeedIndex = i;
                        break;
                    }
                }
            }

            // If the speed can be changed, notify the fsc.
            if (nextSpeedIndex >= 0)
            {
                int newSpeed = CFscConfiguration.Instance.PossibleSpeedValues[nextSpeedIndex];
                this.fsc.SetSpeed(newSpeed);
            }
        }



        public void HandleSetSpeed(int speed)
        {
            IncreaseProgressDialogValue();
        }

        protected void HandleVersionInfoEvent(string versionInfo)
        {
            //mainform.HandleVersionInfoUpdate(versionInfo);
        }

        protected void HandleNewModeEvent(string mode)
        {
            //Logger.Entering(MethodBase.GetCurrentMethod(), "mode = " + mode);
            SorterMode oldSorterMode = fsc.Mode;
            SorterMode newSorterMode = SorterMode.Automatic;
            if (mode == "Maintenance")
            {
                newSorterMode = SorterMode.Maintenance;
            }
            // To prevent multithreading issues we first set the new mode
            // than adapt the gui according to the lod and the new mode.
            fsc.Mode = newSorterMode;
            //mainform.HandleNewMode(oldSorterMode);
            //Logger.Exiting(MethodBase.GetCurrentMethod());

        }





        #region Subscribe to the information list on FSC
        public void ToggleSystemStateRequest(bool startRequest, bool notifyWhenStopped)
        {
            if (startRequest)
            {
                if (String.IsNullOrEmpty(systemStateSubscriptionId))
                {
                    if (CFscConfiguration.Instance.StructureTree.Count > 0)
                    {
                        systemState = new SystemState(Scope.Create(fsc));
                        SubscribeRequestItemList list = systemState.GetSubscribeRequestItemList();
                        if (list != null)
                        {
                            systemStateSubscriptionId =
                                CSubscriptionManager.Instance.StartNewSubscription(
                                    COPCServerConnectionService.Instance.OPCServer,
                                    3000,
                                    list,
                                    HandleSystemStateChanged,
                                    HandleSystemStatePollException);
                        }
                    }
                }
            }
            else
            {
                if (!String.IsNullOrEmpty(systemStateSubscriptionId))
                {
                    CSubscriptionManager.Instance.StopSubscription(systemStateSubscriptionId, notifyWhenStopped);
                    systemStateSubscriptionId = null;
                }
            }
        }

        private void HandleSystemStatePollException(Exception e)
        {
            MessageBox.Show(e.Message);
        }

        private void HandleSystemStateChanged(SubscribePolledRefreshReplyItemList[] listOfChanges)
        {
            //Logger.Entering(MethodBase.GetCurrentMethod());

            //if (this.InvokeRequired)
            //{
            //    HandleSystemStateChangedCallback callback = HandleSystemStateChanged;
            //    Invoke(callback, new object[] { listOfChanges });
            //}
            //else

            try
            {
                if ((listOfChanges != null) && (listOfChanges.Length > 0))
                {
                    foreach (SubscribePolledRefreshReplyItemList itemList in listOfChanges)
                    {
                        foreach (ItemValue value in itemList.Items)
                        {
                            //Logger.Info(MethodBase.GetCurrentMethod(), "Changed system state: " + value.Value);
                            // PR7526 [OGUI] Disable speed change button when running
                            if (value.Value.ToString() == "STARTED")
                            {
                                //this.fscController.Fsc.StatusRunning = true;
                                //ToggleSpeedButtons(false);
                                MessageBox.Show("that is the one that you want to start!!!");
                            }
                            else if (value.Value.ToString() == "STOPPED")
                            {
                                //this.fscController.Fsc.StatusRunning = false;
                                //SetCorrectSpeedButtonsStateForCurrentSpeed(this.fscController.Fsc.Speed);
                                
                            }
                            if (value.ItemName.EndsWith("PState"))
                            {
                                //SetProcessStateLabel(value.Value.ToString());
                            }
                            if (value.ItemName.EndsWith("Mode"))
                            {
                                //SetModeLabel(value.Value.ToString());
                                //CheckForManualModeBlock();
                            }
                        }
                    }
                }
            }
            catch (CFscInvalidStateException fscEx)
            {
                // An unknown state was found, so, we need to reload the configuration.
                //Logger.Error(fscEx.Method, "Invalid state encountered in one of the FSC items.");
                MessageBox.Show(fscEx.Message);
                COPCServerConnectionService.Instance.IsOnline = false;
            }
        }


        //Logger.Exiting(MethodBase.GetCurrentMethod());

        #endregion
        //Method execute after configuration loaded finish.
        protected void HandleReadRemoteFscConfigurationFinish(int newMaximumProgressValue)
        {
            ToggleSystemStateRequest(true, true);
            fsc.FinishReadRemoteFscConfiguration();
            

        }


        protected void HandleConnectionStatusChanged(bool isOnlineStatus, bool notifyUser)
        {
            // If we are offline:
            if (!isOnlineStatus)
            {
                //Set the SorterMode to unknown before handling the visual online status
                //Fsc.Mode = SorterMode.Unknown;
                //progressController.CloseProgressDialog();
            }
            else
            {

            }
            // Ask the main form to show indicator of the online status.
            //mainform.HandleVisualOnlineStatus(isOnlineStatus, notifyUser);
            // Ask the FSC to react to the status change.
            fsc.HandleConnectionStatusChanged(isOnlineStatus);
     

        }

        public string Currenttime
        {
            get { return Ctime; }
            set
            {
                Ctime = value;
                OnPropertyChanged("Currenttime");
            }
        }

        public ObservableCollection<CommandViewModel> Commands
        {
            get
            {
                if (_commands == null)
                {
                    _commands = new ObservableCollection<CommandViewModel>();
                }
                return _commands;
            }
        }

        protected void OnResetButtonExecute()
        {
            // Logger.Entering(MethodBase.GetCurrentMethod());

            bool doReset = false;
            if (!COPCServerConnectionService.Instance.IsOnline)
            {
                // Logger.Info(MethodBase.GetCurrentMethod(), "VIDialog opened");
                //Logger.Info(MethodBase.GetCurrentMethod(), "VIDialog closed");
            }
            else if (CFscUtility.IsOperatorGuiRunning() && fsc.Mode == SorterMode.Maintenance)
            {
                //Logger.Info(MethodBase.GetCurrentMethod(), "VIDialog opened");

                // DialogResult result = VIDialog.ShowQuestionDialog("Fsc", "MaintenanceMode",
                // "MaintenanceModeResetAnyway");
                // doReset = (result == DialogResult.Yes);

                //Logger.Info(MethodBase.GetCurrentMethod(), "VIDialog closed");
            }
            else
            {
                doReset = true;
            }
            if (doReset)
            {
                fsc.Reset();
                // FscDialog.ShowTimedMessageDialog("FSC", "Reset", "BusyWithReset", VIDialog.MessageTypes.Info,
                // VIDialog.ButtonOptions.None);
            }

            //Logger.Exiting(MethodBase.GetCurrentMethod());
        }

        public ICommand buttonCommands
        {
            get { return new RelayCommand(commandHandlers) as ICommand; }
        }


        void commandHandlers(object View)
        {
            try
            {
                if (View == null)
                {
                    //unsubscribe from the information list
                    ToggleSystemStateRequest(false, false);
                    //close the form
                    Application.Current.MainWindow.Close();
                }
                else
                    switch (View.ToString())
                    {
                        case "start":
                            OnStartButtonExecute();
                            break;
                        case "stop":
                            OnStopButtonExecute();
                            break;
                        case "reset":
                            OnResetButtonExecute();
                            break;
                        case "Configuration":
                            if (ipconfigView == null)
                            {
                                ipconfigView = new Views.IPwindow(this);
                                ipconfigView.Show();
                            }
                            break;
                        case "Cancel":
                            if (ipconfigView.IsActive)
                                ipconfigView.Close();
                            ipconfigView = null;
                            break;
                        case "speedUp":
                            ChangeFscSpeed(true);
                            break;
                        case "speedDown":
                            ChangeFscSpeed(false);
                            break;

                        default: throw new ApplicationException();
                    }
            }
            catch (ApplicationException e)
            {
                MessageBox.Show("ApplicationExit", e.Message);
            }
        }


        void OnStartButtonExecute()
        {
            if (!COPCServerConnectionService.Instance.IsOnline)
            {
                //VIDialog.ShowMessageDialog("FSC", "CanNotExecuteActionOfflineTitle",
                //"CanNotExecuteActionOfflineMessage");
            }
            else
            {
                if (fsc.Mode == SorterMode.Maintenance)
                {

                    // VIDialog.ShowMessageDialog("Fsc", "MaintenanceMode", "CannotExecuteActionInMaintenanceMode");
                }
                else
                {
                    fsc.Start();
                }
            }
            //Logger.Exiting(MethodBase.GetCurrentMethod());
        }

        void OnStopButtonExecute()
        {
            if (!COPCServerConnectionService.Instance.IsOnline)
            {
                // VIDialog.ShowMessageDialog("FSC", "CanNotExecuteActionOfflineTitle",
                //"CanNotExecuteActionOfflineMessage");
            }
            else
            {
                if (fsc.Mode == SorterMode.Maintenance)
                {

                    // VIDialog.ShowMessageDialog("Fsc", "MaintenanceMode", "CannotExecuteActionInMaintenanceMode");
                }
                else
                {
                    fsc.Stop();
                }
            }

        }

        public ICommand switchView
        {
            get { return new RelayCommand(OnViewSwitch) as ICommand; }
        }


        void ViewSwitch(string NVID)
        {

            int s = 0, N = Commands.Count;
            foreach (CommandViewModel a in Commands)
            {
                if (a.DisplayName == NVID)
                {
                    s = Commands.IndexOf(a);
                }
            }
            for (int x = N - 1; x > s; x--)
            {
                Commands.RemoveAt(x);
            }

            if (NVID == "Initial Page")
            {
                CurrentView = new Views.GroupView(null);
            }
            else
            {
                if (Commands[s].TType == "Group")
                {
                    CurrentView = new Views.TilesView(NVID);
                }
                else if (Commands[s].TType == "Zone")
                {
                    CurrentView = new Views.ElementView(NVID);
                }

            }
        }

        void OnViewSwitch(object view)
        {
            Button _tile = view as Button;
           
            string NVID = _tile.Tag.ToString();

            int count = NVID.Split('/').Length - 1;
               

                if (count < 2)
                {
                    CurrentView = new Views.TilesView(NVID);
                    Commands.Add(new CommandViewModel(NVID, "Group", new RelayCommand(e => this.ViewSwitch(NVID))));
                }
                else
                {
                    CurrentView = new Views.ElementView(NVID);
                    Commands.Add(new CommandViewModel(NVID, "Element", new RelayCommand(e => this.ViewSwitch(NVID))));
                }
        }

        public FrameworkElement CurrentView
        {
            get { return _currentView; }
            set { _currentView = value; base.OnPropertyChanged("CurrentView"); }
        }

        public string performance
        { get { return _performance; } set { _performance = value; OnPropertyChanged("performance"); } }

        public string NVNC { get; set; }

        public int InitialPGB
        {
            get { return _InitialPGB; }
            set { _InitialPGB = value; base.OnPropertyChanged("InitialPGB"); }
        }

        public string ProgressBarEventName
        {
            get { return _ProgressBarEventName; }
            set { _ProgressBarEventName = value; base.OnPropertyChanged("ProgressBarEventName"); }
        }


        public void IncreaseProgressDialogValue()
        {
            for (int i = 0; i < 25; i++)
            {
                InitialPGB++;

                Thread.Sleep(30);
            
                        int caseSwitch = InitialPGB;
                switch (caseSwitch)
                {
                    case 25:
                        ProgressBarEventName = "Pinging Server...";
                        break;
                   
                    case 50:
                        ProgressBarEventName = "Initializing Reading Configuration ...";
                     
                        break;
                   
                    case 75:
                        ProgressBarEventName = "Starting FSC OGUI...";
                        break;
                   
                    case 100:
                        CurrentView = new Views.GroupView(null);
                        break;
                }
         
            }
        }

        public string FscIpAddress
        {
            get{
                return OperatorGuiApplicationSettings.Instance.FscIpAddress;
                }
            set { OperatorGuiApplicationSettings.Instance.FscIpAddress = value; }
        }
    }

}

